home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / basic / ace_final.lha / ACE_GPL_Release / utils / NAP / NAP.b < prev    next >
Encoding:
Text File  |  1996-08-29  |  29.1 KB  |  979 lines

  1. {* Header *******************************************************************
  2. **                                                                         **
  3. ** Program     :  NAP (New ACE Preprocessor)                               **
  4. ** Author      :  Daniel Seifert <dseifert@hell1og.be.schule.de>           **
  5. **                                                                         **
  6. ** Version     :  2    !!! Pre-release !!!                                 **
  7. ** Revision    :  00b3 !!! testversion !!!                                 **
  8. **                                                                         **
  9. ** work done at:  02,04-07,14-17,23,28-29-Mar-1996                         **
  10. **                28-Apr-1996                                              **
  11. **                04,07,10-May-1996                                        **
  12. **                19-20,23-30-Jun-1996                                     **
  13. **                01-04,07,12,15-19,22-24,26-Jul-1996                      **
  14. **                01-04,11,17-August-1996                                  **
  15. ** language    :  ACE Basic, V2.37                                         **
  16. **                                                                         **
  17. ** description :  a preprocessor especially for ACE Basic                  **
  18. **                                                                         **
  19. ** copyright   :  Daniel Seifert                                           **
  20. ** comment     :  read the manual for further details before 1st use       **
  21. ****************************************************************************}
  22.  
  23.  
  24. DEFint a-Z
  25.  
  26. {* CR is Carriage Return whereas LF is LineFeed.                   *}
  27. STRING   CR,LF SIZE 2
  28.  
  29. {* opt is used to save the options got from the CLI-line and Temp- **
  30. ** file contains the name of the temporary file whereas InFile and **
  31. ** Outfile specifies the files to read from or write to.           *}
  32. STRING   opt SIZE 13
  33. STRING   InFile,OutFile,TempFile SIZE 125
  34. STRING   argument,token,value,object SIZE 100
  35.  
  36. {* These integers are used to mark different conditions which have **
  37. ** a default value that can be inversed by using the options.      *}
  38. SHORTINT Remove_Structs,Remove_Comments,Remove_Defines,Const_Defines
  39. SHORTINT Replace_Defines,Print_Errors
  40.  
  41. {* For buffer handling                                             *}
  42. LONGINT MaxBuffer,BufferPtrBase
  43.  
  44. {* For list handling                                               *}
  45. ADDRESS defines,include,needed_structs,structures
  46.  
  47. {* For file handling                                               *}
  48. ADDRESS PathPtr
  49.  
  50. {* This is the path and filename of the temporary file. As I sus-  **
  51. ** pect T: to point to RAM:t you must change perhaps your assigns? *}
  52. TempFile="t:NAP.temp"
  53.  
  54. {* In the following array the directory names to be searched thru  **
  55. ** for include files.                                              *}
  56. DIM STRING Path(9) SIZE 100
  57. PathPtr=@Path(0)
  58. Path(1)="ACEINCLUDE:"
  59.  
  60. {* This array is used to save the different bases of the lists     *}
  61. DIM ADDRESS StrucBase(3)
  62.  
  63. {* In the following array the beginnings and the sizes of the file **
  64. ** buffers will be stored.                                         *}
  65. DIM ADDRESS BufferPtr(9,1)
  66. BufferPtrBase=@BufferPtr(0,0)
  67.  
  68. ' structure definition
  69.  
  70. STRUCT Node
  71.  address   ln_Succ
  72.  address   ln_Pred
  73.  BYTE      ln_Type
  74.  BYTE      ln_Pri
  75.  ADDRESS   ln_Name
  76. END STRUCT
  77.  
  78. STRUCT _List
  79.  address   lh_Head
  80.  address   lh_Tail
  81.  address   lh_TailPred
  82.  BYTE      lh_Type
  83.  BYTE      l_pad
  84. END STRUCT
  85.  
  86. STRUCT StructNode
  87.  address   ln_Succ
  88.  address   ln_Pred
  89.  BYTE      ln_Type
  90.  BYTE      ln_Pri
  91.  ADDRESS   ln_Name
  92.  ADDRESS   member_types_list
  93. END STRUCT
  94.  
  95. STRUCT DefineNode
  96.  address   ln_Succ
  97.  address   ln_Pred
  98.  BYTE      ln_Type
  99.  BYTE      ln_Pri
  100.  ADDRESS   ln_Name
  101.  STRING    replace SIZE 200
  102.  SHORTINT  countparam
  103. END STRUCT
  104.  
  105. library dos
  106. declare function xRead&(address filehandler,address buffer,longint bytes) library dos
  107. declare function xWrite&(address filehandler,address buffer,longint bytes) library dos
  108. declare function Seek&(address filehandler,longint offset,longint modus) library dos
  109.  
  110. library exec
  111. declare function Remove(address nodeptr) library exec
  112. declare function AddTail&(address listptr,address nodeptr) library exec
  113. declare function FindName&(address listptr,address stringptr) library exec
  114. declare function FreeMem&(address memoryblock,longint bytesize) library exec
  115. declare function AllocMem&(longint bytesize,longint requirements) library exec
  116.  
  117. {* All these sub programs are in NAP_Mods.o to be linked with BLINK. *}
  118. DECLARE SUB ADDRESS  Copy (string text) EXTERNAL
  119. DECLARE SUB SHORTINT legal (STRING text,SHORTINT position) EXTERNAL
  120. DECLARE SUB STRING   UpperCase$(STRING lowercase) EXTERNAL
  121. DECLARE SUB STRING   CutOff (STRING text,SHORTINT FoundSth) EXTERNAL
  122. DECLARE SUB SHORTINT Search2(SHORTINT start,STRING text,STRING snippet) EXTERNAL
  123. DECLARE SUB STRING   Get_name_of_object (SHORTINT startpos, STRING text) EXTERNAL
  124. DECLARE SUB STRING   Get_name_of_object_alt (SHORTINT startpos, STRING text) EXTERNAL
  125. DECLARE SUB STRING   ReplaceC (STRING text,STRING toReplace,STRING replace) EXTERNAL
  126. DECLARE SUB SINGLE   ParseExpr (STRING expression) EXTERNAL
  127.  
  128. { ----------------------------------------------------------------- }
  129.  
  130. {* This function is made to replace the "LINE INPUT #" command. It **
  131. ** is faster and easier to handle because it is a function. It is  **
  132. ** fully compatible with ACE's file handling and gives always the  **
  133. ** same result as "LINE INPUT #".                                  **
  134. ** To made this routine faster there is a buffered reading imple-  **
  135. ** mented. BufferPtrBase points to an array with the dimension (9, **
  136. ** 1), whereas the 1st field is the filenumber. If the second one  **
  137. ** is 0, we are getting the address of the buffer. The length of   **
  138. ** this buffer can be obtained with 0.                             *}
  139. sub string lese(shortint filenumber)
  140.  shared BufferPtrBase
  141.  DIM ADDRESS BufferPointer(9,1) ADDRESS BufferPtrBase
  142.  
  143.  string   text
  144.  address  DataPtr,position,BufferPtr
  145.  longint  DataPos,gelesen,MaxBuffer
  146.  shortint escape
  147.  
  148.  external longint _StartData
  149.  
  150.  BufferPtr=BufferPointer(filenumber,0)
  151.  
  152.  DataPtr=BufferPtr+2
  153.  DataPos=peekw(BufferPtr)
  154.  
  155.  Repeat
  156.   position=DataPtr+DataPos
  157.   _StartData=position
  158.  
  159.   {* The following assembler routine searches from a specified po- **
  160.   ** sition the memory for an identifer to mark the end of line.   **
  161.   ** If a 0 (NUL) is found the routine assumes that the buffer has **
  162.   ** been read to the end. If it founds something between 1 and 10 **
  163.   ** it thinks that the line is finished.                          *}
  164.   ASSEM
  165.  
  166.          movem.l   a0,(sp)+                ; rescue registers
  167.          move.l    _StartData,a0           ; store in a0 the position
  168.  
  169.     _lese_loop:
  170.  
  171.          cmp.b     #10,(a0)+               ; if >10 then increase
  172.          bgt.s     _lese_loop              ; and repeat
  173.  
  174.          cmp.b     #0,-(a0)                ; if 0 then goto _lese_eof
  175.          beq.s     _lese_eof
  176.  
  177.          move.b    #0,(a0)                 ; otherwise move a 0 to it
  178.          bra.s     _lese_end               ; and exit
  179.  
  180.     _lese_eof:
  181.  
  182.          sub.l     a0,a0
  183.  
  184.     _lese_end:
  185.  
  186.          move.l    a0,_StartData           ; store result
  187.          movem.l   -(sp),a0                ; restore registers
  188.  
  189.   END ASSEM
  190.  
  191.   if _StartData=0 then
  192.    text=text+cstr(position)
  193.    MaxBuffer=BufferPointer(filenumber,1)-3
  194.    gelesen=xRead&(handle(filenumber),DataPtr,maxbuffer)
  195.    case
  196.     gelesen=0        :Poke DataPtr+maxbuffer,1:lese=text:exit sub
  197.     gelesen<MaxBuffer:Poke DataPtr+gelesen,0
  198.    end case
  199.    DataPos=0
  200.   else
  201.    ++escape
  202.    string dummy address position
  203.    DataPos=DataPos+len(dummy)
  204.    ++DataPos
  205.    Pokew BufferPtr,DataPos
  206.    dummy=text+dummy
  207.   end if
  208.  until escape
  209.  lese=dummy
  210. end sub
  211.  
  212. ASSEM
  213. _StartData: dc.l 0
  214. end assem
  215.  
  216. {* ENDE closes all files and kills the temporary file.  It is used **
  217. ** when doing a CTRL-C or when NAP finishs.                        *}
  218. SUB ende
  219.  SHARED TempFile,OutFile,BufferPtrBase
  220.  DIM ADDRESS BufferPtr(9,1) ADDRESS BufferPtrBase
  221.  
  222.  FOR i=1 TO 9
  223.   CLOSE #i
  224.   if BufferPtr(i,0) then call FreeMem&(BufferPtr(i,0),BufferPtr(i,1))
  225.  NEXT
  226.  
  227.  CLEAR ALLOC
  228.  If TempFile<>OutFile then KILL TempFile
  229.  STOP
  230. END SUB
  231.  
  232.  
  233. {* This routine prints an error message to standard output. There- **
  234. ** fore the Print_Errors variable must be set, otherwise the error **
  235. ** message would be suppressed.                                    *}
  236. sub PrErr (string text)
  237.  shared Print_Errors
  238.  
  239.  if Print_Errors then print "-- Error : "text
  240. end sub
  241.  
  242. {* This sub program is made to replace the "PUT #" command. It is  **
  243. ** also faster and 100% compatible with the "PUT #" command !      *}
  244. sub schreibe(shortint filenumber,string text)
  245.  shared LF
  246.  longint geschrieben,l
  247.  
  248.  text=text+LF
  249.  l=len(text)
  250.  geschrieben=xWrite&(handle(filenumber),@text,l)
  251.  IF geschrieben<l THEN CALL PrErr ("Error writing to file!"):CALL ende
  252. END SUB
  253.  
  254. {* ReplaceDefines - Checks every word within a string whether it's **
  255. **                  a define and replaces it if necessary          **
  256. **                                                                 **
  257. **   Syntax : replaced = ReplaceDefines(defineslist,text)          **
  258. **                                                                 **
  259. **     replaced       : (string) <text> with every used define re- **
  260. **                      placed                                     **
  261. **     defineslist    : (address) pointer to the list of defines   **
  262. **     text           : (string) string to be checked              *}
  263.  
  264. sub string ReplaceDefines (address defptr,string text)
  265.  string   object,replace,param
  266.  shortint cparam,found,foundsth,position
  267.  declare struct definenode *defines
  268.  
  269.  ++foundsth
  270.  repeat
  271.   object=get_name_of_object_alt(foundsth,text)
  272.   foundsth=search2(foundsth,text,object)
  273.   defines=FindName&(defptr,@object)
  274.   if defines then
  275.    replace=defines->replace
  276.    ' Do we have to parse any comments?
  277.    IF defines->countparam THEN
  278.     ' yes - look for begin of parameter list
  279.     position=search2(foundsth,text,"(")
  280.     IF position=0 THEN
  281.      ' Funny. There have to be params but there are none :(
  282.      PrErr("Corrupt define "+cstr(defines->ln_name))
  283.     ELSE
  284.      cparam=0
  285.      WHILE peek(@text+position-1)<>41        ' 41 = ")"
  286.       param=get_name_of_object_alt(position,text)
  287.       position=position+LEN(param)
  288.       ++position
  289.       ++cparam
  290.       a$=chr$(cparam)
  291.       found=search2(1,replace,a$)
  292.       WHILE found
  293.        ++found
  294.        replace=LEFT$(replace,found-2)+param+MID$(replace,found)
  295.        found=search2(found,replace,a$)
  296.       WEND
  297.      WEND
  298.      ++position
  299.     END IF
  300.    ELSE
  301.     position=foundsth+LEN(object)
  302.    END IF
  303.    text=LEFT$(text,foundsth-1)+replace+MID$(text,position)
  304.    foundsth=foundsth+len(replace)
  305.   else
  306.    foundsth=foundsth+len(object)
  307.   end if
  308.  until peek(@object)=0
  309.  
  310.  ReplaceDefines=text
  311. end sub
  312.  
  313. {* This routine replaces C-comments (/* and */) through ACE ones   **
  314. ** and checks whether there is a define                            *}
  315. SUB STRING Convert (STRING text,address defptr)
  316.  SHARED Replace_Defines
  317.  DECLARE STRUCT definenode *defines
  318.  
  319.  SHORTINT foundsth,position,cparam,found
  320.  STRING   replace,param,object
  321.  
  322.  {* Why should we waste time by using this sub program if the      **
  323.  ** string is empty ?                                              *}
  324.  IF peek(@text)=0 then Convert="":exit sub
  325.  
  326.  {* You must first replace */ and then /*.  This is very important **
  327.  ** and not paying attention to that would lead to a processed co- **
  328.  ** de where all comments begin with { but do end with a */. This  **
  329.  ** has to do with the Legal-routine which's used to check whether **
  330.  ** "/*" or "*/" is within a string or a comment.                  *}
  331.  text=ReplaceC(text,"*/","}")
  332.  text=ReplaceC(text,"/*","{")
  333.  
  334.  {* If we are allowed to replace defines within the source code we **
  335.  ** check every word within the line if it's a defined alias. Here **
  336.  ** one can make things like removing all  PRINT  commands through **
  337.  ** the faster PRINTS command  (if the program just uses intuition **
  338.  ** windows)                                                       **
  339.  ** Note: Defines have a higher priority than the commands of the  **
  340.  **       programming language since NAP just checks whether there **
  341.  **       is something defined within the string but does not care **
  342.  **       of removing real commands!                               *}
  343.  IF Replace_Defines then text=ReplaceDefines(DefPtr,text)
  344.  
  345.  convert=text
  346. END SUB
  347.  
  348. SUB address ReserveMem (shortint filenumber)
  349.  shared BufferPtrBase,MaxBuffer
  350.  address ActBuffer
  351.  longint filesize
  352.  
  353.  DIM ADDRESS BufferPtr(9,1) ADDRESS BufferPtrBase
  354.  
  355.  filesize=seek&(handle(filenumber),0,1)
  356.  filesize=seek&(handle(filenumber),0,-1)
  357.  if filesize<MaxBuffer then filesize=filesize+3 else filesize=MaxBuffer+3
  358.  ActBuffer=AllocMem&(fileSize,65536&)
  359.  
  360.  if ActBuffer=0 then
  361.   PrErr("Not enough memory to create new filebuffer!")
  362.   ende
  363.  end if
  364.  
  365.  BufferPtr(filenumber,0)=ActBuffer
  366.  BufferPtr(filenumber,1)=filesize
  367.  ReserveMem=ActBuffer+filesize-1
  368. END SUB
  369.  
  370. { -------------------------------------------------------------------------- }
  371.  
  372. {* This sub program adds a specific file to the TempFile.          **
  373. ** Params :  filenumber  - next free filenumber                    **
  374. **           filename    - name (incl path) of file to be included *}
  375.  
  376. SUB AddToTemp (SHORTINT filenumber,STRING filename)
  377.  SHARED CR,Const_Defines,Remove_Structs,Remove_Defines
  378.  SHARED MaxBuffer,Remove_Comments,BufferPtrBase,include,defines
  379.  SHARED needed_structs,structures,PathPtr
  380.  
  381.  DIM ADDRESS BufferPtr(9,1) ADDRESS BufferPtrBase
  382.  DIM STRING Path(9) SIZE 100% ADDRESS PathPtr
  383.  
  384.  ON BREAK CALL ende
  385.  BREAK ON
  386.  
  387.  FOR i=0 to 9
  388.   open "I",filenumber,Path(i)+filename
  389.   if handle(filenumber) then exit for
  390.  NEXT
  391.  if handle(filenumber)=0 then
  392.   PrErr ("Could not open "+filename+"!")
  393.   EXIT SUB
  394.  END IF
  395.  
  396.  address FileReady
  397.  FileReady=ReserveMem(filenumber)
  398.  
  399.  STRING   object,toparse,fname,command,param,name_of_struct SIZE 200
  400.  STRING   text,BigText,replace
  401.  SHORTINT inComment,in_Struct,if_depth,valid_depth
  402.  
  403.  STRING definition size 10
  404.  STRING declaration size 20
  405.  STRING reserved size 55
  406.  
  407.  definition="STRUCT "
  408.  declaration="DECLARE STRUCT "
  409.  reserved=" LONGINT SHORTINT END STRUCT BYTE ADDRESS STRING "
  410.  
  411.  DECLARE STRUCT _List *substruct
  412.  DECLARE STRUCT Node *EmptyNode
  413.  DECLARE STRUCT DefineNode *EmptyDefine
  414.  DECLARE STRUCT StructNode *EmptyStruct
  415.  
  416.  
  417.  WHILE peek(fileready)=0
  418.   if inComment then
  419.    inComment=0
  420.    repeat
  421.     text=ReplaceC(lese(filenumber),"*/","}")
  422.     foundsth=search2(1,text,"}")
  423.     if foundsth=0 then
  424.      if Remove_Comments=0 then call schreibe(1,text)
  425.     else
  426.      if Remove_Comments=0 then call schreibe(1,left$(text,FoundSth))
  427.      text=mid$(text,foundsth+1)
  428.     end if
  429.    until foundsth
  430.   else
  431.    text=lese(filenumber)
  432.   end if
  433.  
  434.  
  435.   {* 1st look for preprocessor commands.  These commands work with **
  436.   ** token defined via #define. Therefore defines must not be re-  **
  437.   ** placed !                                                      *}
  438.  
  439.   ' is there a preprocessor command within this line?
  440.   IF PEEK(@text)=35 THEN                 { 35 = "#" }
  441.    BigText=UpperCase$(text)
  442.    command=get_name_of_object(2,BigText)
  443.  
  444.    {* This is for  "#IF DEFINED <token>"  commands. The other #IF  **
  445.    ** variation can be found further down.                         *}
  446.    IF command="IF" THEN                       ' <expression>
  447.     object=get_name_of_object(4,BigText)
  448.     if object="DEFINED" then
  449.      if valid_depth=if_depth then
  450.       found=search2(4,BigText,object)
  451.       object=get_name_of_object_alt(found+8,BigText)
  452.       if FindName&(Defines,@object) then ++valid_depth
  453.      end if
  454.      ++if_depth
  455.      {* Since we processed this variation of the "#IF" command, we **
  456.      ** must prevent the other #IF-processing routine to process   **
  457.      ** this one again. So we destroy it.                          *}
  458.      poke @text+1,79
  459.     else
  460.      {* This is not "#IF DEFINED <token>".  Therefore it has to be **
  461.      ** processed again below.                                     *}
  462.     end if
  463.    END IF
  464.  
  465.    IF command="IFDEF" THEN                     ' <token>
  466.     if if_depth=valid_depth then
  467.      object=get_name_of_object_alt(7,text)
  468.      if FindName&(defines,@object) then ++valid_depth
  469.     end if
  470.     ++if_depth
  471.    END IF
  472.  
  473.    IF command="IFNDEF" THEN                    ' <token>
  474.     if if_depth=valid_depth then
  475.      object=get_name_of_object(9,text)
  476.      if FindName&(defines,@object)=0 then ++valid_depth
  477.     end if
  478.     ++if_depth
  479.    END IF
  480.   END IF
  481.  
  482.   {* Now we test again of existing preprocessor commands. But this **
  483.   ** time tokens must be replaced!                                 *}
  484.  
  485.   text=convert(text,defines)
  486.   BigText=uppercase$(text)
  487.  
  488.   ' is there a preprocessor command within this line?
  489.   IF PEEK(@text)=35 THEN                 { 35 = "#" }
  490.    command=get_name_of_object(2,BigText)
  491.  
  492.    IF command="ASSERT" THEN                    ' <expression>
  493.     PrErr("#ASSERT not yet implemented")
  494.    END IF
  495.  
  496.    IF command="ELIF" THEN                      ' <expression>
  497.     IF if_depth=valid_depth THEN
  498.      IF if_depth=0 THEN
  499.       PrErr("#ELIF without #IF #ENDIF")
  500.      ELSE
  501.       --valid_depth
  502.      END IF
  503.     ELSE
  504.      IF valid_depth+1=if_depth THEN
  505.       IF ParseExpr(MID$(text,7)) THEN ++valid_depth
  506.      END IF
  507.     END IF
  508.    END IF
  509.  
  510.    IF command="ENDIF" THEN
  511.     if valid_depth=if_depth then --valid_depth
  512.     --if_depth
  513.     if if_depth<0 then
  514.      PrErr ("Too many #ENDIF")
  515.      if_depth=0
  516.      valid_depth=0
  517.     end if
  518.    END IF
  519.  
  520.    IF command="ERROR" THEN                     ' <expression>
  521.     PrErr("#ERROR not yet implemented")
  522.    END IF
  523.  
  524.    IF command="IF" THEN                        ' <expression>
  525.     IF if_depth=valid_depth then
  526.      IF ParseExpr(MID$(text,3)) THEN ++valid_depth
  527.     END IF
  528.     ++if_depth
  529.    END IF
  530.  
  531.    IF command="LINE" THEN                      ' <number> <filename>
  532.     PrErr("#LINE not yet implemented")
  533.    END IF
  534.  
  535.    IF command="PRAGMA" THEN                    ' <anything>
  536.     PrErr("#PRAGMA not yet implemented")
  537.    END IF
  538.  
  539.    IF command="DEBUG" THEN
  540.     PrErr("#DEBUG not yet implemented")
  541.    END IF
  542.  
  543.    IF command="NODEBUG" THEN
  544.     PrErr("#NODEBUG not yet implemented")
  545.    END IF
  546.  
  547.    IF command="ELSE" THEN
  548.     if if_depth=valid_depth then --valid_depth else ++valid_depth
  549.    END IF
  550.  
  551.    IF command="UNDEF" THEN
  552.     ' what shall we undefine?
  553.     object=get_name_of_object(8,BigText)
  554.     emptydefine=FindName&(defines,@object)
  555.     IF emptydefine=0 then
  556.      PrErr ("Could not undefine "+object)
  557.     else
  558.      Remove&(emptydefine)
  559.     end if
  560.    END IF
  561.  
  562.    IF command="INCLUDE" THEN
  563.     ' try to include a file, get name of include file
  564.     fname=get_name_of_object(10,BigText)
  565.     ' remove <brackets>
  566.     fname=MID$(fname,2,LEN(fname)-2)
  567.  
  568.     ' file already included? If not, then
  569.     IF FindName&(include,@fname)=0 THEN
  570.      ' save include file name
  571.      EmptyNode=alloc(sizeof(Node),7)
  572.      EmptyNode->ln_name=Copy(fname)
  573.      AddTail&(include,EmptyNode)
  574.  
  575.      ' include file
  576.      AddToTemp(filenumber+1,fname)
  577.  
  578.      ' reset string contents
  579.      definition="STRUCT "
  580.      reserved=" LONGINT SHORTINT END STRUCT BYTE ADDRESS STRING "
  581.      command="definition
  582.      declaration="DECLARE STRUCT "
  583.     END IF
  584.    END IF
  585.  
  586.    IF command="DEFINE" AND Remove_Defines=0 THEN
  587.     EmptyDefine=alloc(sizeof(DefineNode),7)
  588.     EmptyDefine->ln_name=Copy(get_name_of_object_alt(8,text))
  589.     toparse=get_name_of_object(8,text)
  590.     foundsth=search2(8,text,toparse)
  591.     poke @replace,0
  592.  
  593.     REPEAT
  594.      IF peek(@replace)=0 THEN
  595.       replace=MID$(text,foundsth+LEN(toparse))
  596.      ELSE
  597.       text=Convert(lese(filenumber),defines)
  598.       replace=LEFT$(replace,LEN(replace)-1)+text
  599.      END IF
  600.      a$=RIGHT$(replace,1)
  601.     UNTIL a$<>"\" AND a$<>"~"
  602.  
  603.     foundsth=search2(1,replace,"{")
  604.     IF foundsth THEN
  605.      replace=LEFT$(replace,foundsth-1)
  606.     else
  607.      foundsth=search2(1,replace,"'")
  608.      IF foundsth THEN replace=LEFT$(replace,foundsth-1)
  609.     end if
  610.  
  611.     cparam=0
  612.     foundsth=search2(1,toparse,"(")
  613.  
  614.     IF foundsth THEN
  615.      IF Const_Defines THEN
  616.       PrErr (toparse+" is not legal when option Q is used !")
  617.      ELSE
  618.       length=len(toparse)
  619.       WHILE peek(@toparse+foundsth-1)<>41 AND foundsth<Length
  620.        param=get_name_of_object_alt(foundsth,toparse)
  621.        foundsth=foundsth+LEN(param)
  622.        ++foundsth
  623.        ++cparam
  624.        found=1
  625.        REPEAT
  626.         found=search2(found,replace,param)
  627.        UNTIL param=get_name_of_object_alt(found-1,replace)
  628.        replace=LEFT$(replace,found-1)+CHR$(cparam)+MID$(replace,found+LEN(param))
  629.       WEND
  630.      END IF
  631.     END IF
  632.  
  633.     emptydefine->replace=replace
  634.     emptydefine->countparam=cparam
  635.  
  636.     IF Const_Defines THEN
  637.      schreibe(1,"CONST "+cstr(emptydefine->ln_name)+"="+STR$(VAL(replace)))
  638.      IF cparam=0 then call AddTail&(defines,emptydefine)
  639.     else
  640.      AddTail&(defines,emptydefine)
  641.     end if
  642.    END IF
  643.  
  644.    foundsth=search2(1,text,"{")
  645.    IF foundsth THEN text=MID$(text,foundsth) else poke @text,0
  646.  
  647.   ELSE
  648.  
  649.    if if_depth>valid_depth then
  650.     poke @text,0
  651.     poke @BigText,0
  652.    end if
  653.  
  654.    ' is there a structure definition?
  655.    struct_def=search2(1,BigText,definition)
  656.  
  657.    If struct_def then
  658.     struct_dec=search2(1,Bigtext,declaration)
  659.  
  660.     IF struct_dec then
  661.      if legal(text,struct_dec) and Remove_Structs THEN
  662.       ' save name of declared structure in list
  663.       EmptyNode=alloc(sizeof(node),7)
  664.       emptynode->ln_name=copy(get_name_of_object(15+struct_dec,BigText))
  665.       AddTail&(needed_structs,EmptyNode)
  666.      end if
  667.     ELSE
  668.      if legal(text,struct_def) and in_Struct=0 THEN
  669.       proceed=1
  670.       if struct_def>1 then
  671.        if get_name_of_object_alt(struct_def-1,text)<>definition then proceed=0
  672.       end if
  673.  
  674.       if proceed then
  675.        in_struct=1
  676.        if Remove_Structs then
  677.         ' yes, it is -> save name of structure in list
  678.         EmptyStruct=alloc(sizeof(structnode),7)
  679.         EmptyStruct->ln_name=Copy(get_name_of_object(6+struct_def,Bigtext))
  680.         EmptyStruct->member_types_list=ALLOC(SIZEOF(_list),7)
  681.         substruct=emptystruct->member_types_list
  682.         AddTail&(structures,EmptyStruct)
  683.         substruct->lh_Head=substruct+4
  684.         substruct->lh_TailPred=substruct
  685.        end if
  686.       end if
  687.      end if
  688.     end if
  689.    end if
  690.  
  691.    IF in_Struct=1 then
  692.     ' name of substruct
  693.     if Const_Defines then text=ReplaceDefines(defines,text):BigText=UpperCase$(text)
  694.     name_of_struct=get_name_of_object(1,BigText)
  695.     if name_of_struct="END" then
  696.      in_Struct=0
  697.     else
  698.      IF Remove_Structs then
  699.       if search2(1,reserved," "+name_of_struct+" ")=0 THEN
  700.        emptynode=alloc(sizeof(node),7)
  701.        emptynode->ln_name=copy(name_of_struct)
  702.        AddTail&(substruct,emptynode)
  703.       end if
  704.      END IF
  705.     END IF
  706.    END IF
  707.   END IF
  708.  
  709.   ' REMOVE COMMENTS
  710.  
  711.   FoundSth=search2(1,text,"{")
  712.   IF FoundSth THEN
  713.    FoundEnd=search2(FoundSth,text,"}")
  714.    IF FoundEnd THEN
  715.     IF Remove_Comments THEN text=cutoff(text,FoundSth)+~
  716.                                  RIGHT$(text,LEN(text)-FoundEnd)
  717.    ELSE
  718.     IF Remove_Comments THEN text=cutoff(text,FoundSth)
  719.     inComment=1
  720.    END IF
  721.   END IF
  722.  
  723.   IF Remove_Comments THEN
  724.    FoundSth=search2(1,text,"'")
  725.    IF FoundSth THEN text=cutoff(text,FoundSth)
  726.    FoundSth=search2(1,UpperCase$(text),"REM ")
  727.    IF FoundSth THEN text=cutoff(text,FoundSth)
  728.   END IF
  729.  
  730.   IF LEN(text) THEN
  731.    schreibe(1,text)
  732.    KillEmpty=0
  733.   ELSE
  734.    if KillEmpty=0 then
  735.     schreibe(1," ")
  736.     ++KillEmpty
  737.    end if
  738.   end if
  739.  WEND
  740.  
  741.  if if_depth then call PrErr("#IF without #ENDIF")
  742.  break off
  743.  CLOSE #filenumber
  744.  FreeMem&(BufferPtr(filenumber,0),BufferPtr(filenumber,1))
  745.  BufferPtr(filenumber,0)=0
  746. END SUB
  747.  
  748. { -------------------------------------------------------------------------- }
  749.  
  750. SUB RemoveStuff
  751.  ' remove comments, unused structs or just copy the contents of the temp
  752.  ' file to the output file.
  753.  
  754.  ' see all above
  755.  SHARED needed_structs,structures,BufferPtrBase
  756.  DIM ADDRESS BufferPtr(9,1) ADDRESS BufferPtrBase
  757.  
  758.  address FileReady
  759.  FileReady=ReserveMem(1)
  760.  
  761.  ON BREAK CALL ende
  762.  BREAK ON
  763.  
  764.  STRING   object,text,definition,declaration SIZE 100
  765.  STRING   name_of_struct,BigText SIZE 100
  766.  SHORTINT in_Struct
  767.  
  768.  definition="STRUCT "
  769.  declaration="DECLARE STRUCT "
  770.  
  771.  DECLARE STRUCT _List *structs,*substruct
  772.  DECLARE STRUCT Node *EmptyNode
  773.  DECLARE STRUCT StructNode *EmptyStruct
  774.  
  775.  structs=structures
  776.  REPEAT
  777.   EmptyStruct=structs->lh_Head
  778.   FoundSth=0
  779.   WHILE EmptyStruct->ln_Succ
  780.    object=cstr(EmptyStruct->ln_name)
  781.    IF FindName&(needed_structs,object) THEN
  782.     substruct=emptystruct->member_types_list
  783.     emptynode=substruct->lh_head
  784.     WHILE emptynode->ln_succ
  785.      object=cstr(emptynode->ln_name)
  786.      IF FindName&(needed_structs,object)=0 THEN
  787.       AddTail&(needed_structs,emptynode)
  788.       FoundSth=1
  789.      END IF
  790.      emptynode=emptynode->ln_succ
  791.     WEND
  792.    END IF
  793.    emptystruct=emptystruct->ln_succ
  794.   WEND
  795.  UNTIL FoundSth=0
  796.  
  797.  WHILE peek(FileReady)=0
  798.   text=lese(1)
  799.   BigText=UpperCase$(text)
  800.  
  801.   ' REMOVE STRUCTS
  802.  
  803.   IF in_Struct=0 THEN
  804.    struct_def=search2(1,Bigtext,definition)
  805.  
  806.    IF struct_def THEN
  807.     proceed=1
  808.     if search2(1,Bigtext,declaration) then
  809.      proceed=0
  810.     else
  811.      if struct_def>1 then
  812.       if get_name_of_object_alt(struct_def-1,BigText)<>definition THEN proceed=0
  813.      end if
  814.     end if
  815.  
  816.     IF proceed and legal(text,struct_def) THEN
  817.      ' if it is really a definition and if it is not within a comment,
  818.      ' then get the name of the struct
  819.      name_of_struct=get_name_of_object(struct_def+6,BigText)
  820.  
  821.      ' does we need this struct?
  822.      IF FindName&(needed_structs,name_of_struct)=0 THEN
  823.       ' no
  824.       REPEAT
  825.        text=lese(1)
  826.       UNTIL search2(1,UpperCase$(text),"END STRUCT") OR Peek(FileReady)
  827.       text=lese(1)
  828.      ELSE
  829.       in_Struct=1
  830.      END IF
  831.     END IF
  832.    END IF
  833.   END IF
  834.  
  835.   IF in_Struct THEN
  836.    IF UpperCase$(get_name_of_object(1,text))="END" then in_Struct=0
  837.   END IF
  838.  
  839.   schreibe(2,text)
  840.  WEND
  841.  
  842.  {* The BREAK OFF is life-rescuing: If the user would press CTRL-C **
  843.  ** after the memory is freed but before this is stored, the ENDE- **
  844.  ** routine would free the memory again -> would cause a 81000009! *}
  845.  break off
  846.  FreeMem&(BufferPtr(1,0),BufferPtr(1,1))
  847.  BufferPtr(1,0)=0
  848. END SUB
  849.  
  850. SUB Usage
  851.  ?
  852.  ? "Usage :"
  853.  ?
  854.  ? " "ARG$(0)" [-options] <infile> <outfile>"
  855.  ?
  856.  ? " options are :  s   -> do not remove unused structs"
  857.  ? "                c   -> do not remove comments"
  858.  ? "                q   -> write #defines as CONST"
  859.  ? "                i   -> ignore defines"
  860.  ? "                e   -> suppress error messages"
  861.  ? "                b## -> set buffer to ## kilobytes"
  862.  ? "                h   -> this text"
  863.  ? "                d<token>[=<replacement>] -> define token"
  864.  ? "                p<directory>             -> add includedirectory"
  865.  ? "                u<token>                 -> undefine token"
  866.  ?
  867.  ? "Read the manual for more information."
  868.  Ende
  869. END SUB
  870.  
  871. { -------------------------------------------------------------------------- }
  872.  
  873. start2&=TIMER
  874. ? "New ACE Preprocessor version 2.00beta3, copyright © 1996 Daniel Seifert"
  875.  
  876. {* The defaults of the options                                     *}
  877.  
  878. Remove_Structs  = 1               ' do remove unused structures
  879. Remove_Comments = 1               ' do remove EVERY comment
  880. Remove_Defines  = 0               ' do not ignore defines
  881. Const_Defines   = 0               ' do not replace defines by CONST
  882. Replace_Defines = 1               ' but do replace defines directly
  883. Print_Errors    = 1               ' do print errors/warnings
  884.  
  885.  
  886. DECLARE STRUCT _List *liste
  887. DECLARE STRUCT DefineNode *emptydefine
  888.  
  889. For i=0 to 3
  890.  liste=ALLOC(SIZEOF(_list),7)
  891.  StrucBase(i)=liste
  892.  liste->lh_Head=liste+4
  893.  liste->lh_TailPred=liste
  894. Next
  895.  
  896. include        = StrucBase(0)
  897. needed_structs = StrucBase(1)
  898. defines        = StrucBase(2)
  899. structures     = StrucBase(3)
  900.  
  901. poke @InFile,0
  902. poke @OutFile,0
  903.  
  904. ' ACE comments
  905.  
  906. LF=CHR$( 10)
  907. CR=CHR$( 11)
  908.  
  909. FOR i=1 TO ARGCOUNT
  910.  argument=ARG$(i)
  911.  IF PEEK(@argument)=45 THEN                     ' 45 = "-"
  912.   FOR j=2 TO LEN(argument)
  913.    opt=UpperCase$(MID$(argument,j,1))
  914.    CASE
  915.     opt="S":Remove_structs=0
  916.     opt="C":Remove_Comments=0
  917.     opt="I":SWAP Remove_Defines,Replace_Defines
  918.     opt="Q":Const_Defines=1
  919.     opt="E":Print_Errors=0
  920.     opt="B":MaxBuffer=val(mid$(argument,j+1)):exit for
  921.     opt="D":token=get_name_of_object_alt(j+1,argument):~
  922.             value=mid$(argument,search2(3,argument,token)+len(token)+1):~
  923.             if peek(@value)=0 then value="1":~
  924.             emptydefine=alloc(sizeof(definenode),7):~
  925.             emptydefine->ln_name=copy(token):~
  926.             emptydefine->replace=value:~
  927.             emptydefine->countparam=0:~
  928.             AddTail&(defines,emptydefine):~
  929.             exit for
  930.     opt="P":object=mid$(argument,j+1):~
  931.             for x=2 to 9:~
  932.              if peek(@Path(x))=0 then Path(x)=object:exit for:~
  933.             next:~
  934.             exit for
  935.     opt="U":token=mid$(argument,j+1):~
  936.             if FindName&(defines,@token) then call Remove(FindName&(defines,@token))
  937.     100=100:CALL usage
  938.    END CASE
  939.   NEXT
  940.  ELSE
  941.   IF peek(@InFile)=0 THEN
  942.    InFile=argument
  943.   ELSE
  944.    IF peek(@OutFile) THEN CALL Usage
  945.    OutFile=argument
  946.   END IF
  947.  END IF
  948. NEXT
  949. IF peek(@OutFile)=0 then CALL Usage
  950. if MaxBuffer=0 or MaxBuffer>64 then MaxBuffer=32
  951. MaxBuffer=MaxBuffer*1000
  952.  
  953. OPEN "I",1,InFile
  954. OPEN "O",2,OutFile
  955. CLOSE #1
  956. CLOSE #2
  957. IF ERR THEN
  958.  PrErr ("Could not open file to read/write.")
  959.  ende
  960. END IF
  961.  
  962. IF Remove_Defines then Const_Defines=0
  963. IF Const_Defines then Replace_Defines=0
  964. if Remove_Structs=0 then TempFile=OutFile
  965.  
  966. OPEN "O",1,TempFile
  967. AddToTemp(2,InFile)
  968.  
  969.  
  970. If Remove_Structs then
  971.  CLOSE #1
  972.  OPEN "I",1,TempFile
  973.  OPEN "O",2,OutFile
  974.  RemoveStuff
  975. end if
  976.  
  977. ? "Elapsed time :"TIMER-start2&
  978. ende
  979.